<template>
  <div ref="chartRef" :style="{ height, width }"></div>
</template>

<script lang="ts">
  import * as Color from '/@/utils/ColorDefault';
  import * as MathUtil from '/@/utils/MathUtil';
  import { defineComponent, PropType, ref, Ref, reactive, watchEffect } from 'vue';
  import { useECharts } from '/@/hooks/web/useECharts';
  import { cloneDeep } from 'lodash-es';
  const LABLE_FONT_SIZE = 12;
  // const REST_WIDTH = 50;
  // const REST_HEIGHT = 21;

  export default defineComponent({
    name: 'LineRateChart',
    props: {
      dataList: Array,
      seriesNames: Array,
      formatter: {
        type: String,
        default: 'currencyWNFormatter|0',
      },
      showLast: { type: Boolean, default: true },
      width: {
        type: String as PropType<string>,
        default: '100%',
      },
      height: {
        type: String as PropType<string>,
        // default: 'calc(100vh - 78px)',
        default: '500px',
      },
    },
    setup(props) {
      const chartRef = ref<HTMLDivElement | null>(null);
      const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
      const formatter = props.formatter;
      const [f, dot] = formatter.split('|');
      const zeroPoint = ref(null);
      const renderCustomItem = (params, api) => {
        const formatter = props.formatter;
        const [f, dot] = formatter.split('|');
        // const xValue = api.value(0);
        const value1 = api.value(1);
        const value2 = api.value(2);
        const diff = MathUtil.diff(value1, value2);

        // 计算每个格子的中心x坐标
        const columnWidth = params.coordSys.width / props.dataList.length;
        const x = params.coordSys.x + columnWidth * params.dataIndex + columnWidth / 2;
        // graphic标签的top起点和行高要与option.graphic一致
        const baseY = params.coordSys.y + params.coordSys.height + 42; // 更精确的纵向起点
        const rowGap = 38; // 更精确的行高

        return {
          type: 'group',
          children: [
            // 实际值
            {
              type: 'group',
              position: [x, baseY + rowGap * 0],
              children: [
                {
                  type: 'rect',
                  shape: {
                    x: -24,
                    y: -12,
                    width: 48,
                    height: 24,
                    r: 12,
                  },
                  style: {
                    fill: '#F5F5F5',
                  },
                },
                {
                  type: 'text',
                  position: [0, -5],
                  style: {
                    text: MathUtil[f](value1, dot),
                    textAlign: 'center',
                    textBaseline: 'middle',
                    fontSize: 12,
                    fill: '#333',
                  },
                },
              ],
            },
            // 预测值
            {
              type: 'group',
              position: [x, baseY + rowGap * 0.76],
              children: [
                {
                  type: 'rect',
                  shape: {
                    x: -24,
                    y: -12,
                    width: 48,
                    height: 24,
                    r: 12,
                  },
                  style: {
                    fill: '#F5F5F5',
                  },
                },
                {
                  type: 'text',
                  position: [0, -5],
                  style: {
                    text: MathUtil[f](value2, dot),
                    textAlign: 'center',
                    textBaseline: 'middle',
                    fontSize: 12,
                    fill: '#333',
                  },
                },
              ],
            },
            // 准确率
            {
              type: 'group',
              position: [x, baseY + rowGap * 1.57],
              children: [
                {
                  type: 'rect',
                  shape: {
                    x: -24,
                    y: -12,
                    width: 48,
                    height: 24,
                    r: 12,
                  },
                  style: {
                    fill: diff >= -0.05 && diff <= 0.05 ? Color.COLOR_GREEN : Color.COLOR_RED,
                  },
                },
                {
                  type: 'text',
                  position: [0, -5],
                  style: {
                    text: MathUtil.percent2DFormatter(diff, 0),
                    textAlign: 'center',
                    textBaseline: 'middle',
                    fontSize: 12,
                    fill: Color.COLOR_WHITE,
                  },
                },
              ],
            },
          ],
        };
      };
      const option = reactive({
        color: [Color.COLOR_DEEP_BLUE, Color.COLOR_MAIN_PURPLE],
        legend: {
          show: true,
          icon: 'roundRect',
          right: '2%',
          top: '2%',
          orient: 'horizontal',
          backgroundColor: Color.COLOR_LIGHT_GRAY,
          borderRadius: 8,
          padding: [8, 10],
        },
        grid: {
          top: '15%',
          left: '5%',
          right: '5%',
          bottom: '30%',
          containLabel: true,
        },
        graphic: [
          // 实际
          {
            type: 'group',
            left: 10,
            top: '72%',
            children: [
              {
                type: 'rect',
                shape: { width: 48, height: 24, r: 12 },
                style: { fill: '#E9E7F2' },
              },
              {
                type: 'text',
                left: 14,
                top: 6,
                style: {
                  text: props.seriesNames[0],
                  fill: '#000',
                  textAlign: 'center',
                  textBaseline: 'middle',
                  fontSize: LABLE_FONT_SIZE,
                },
              },
            ],
          },
          // 预测
          {
            type: 'group',
            left: 10,
            top: '78%',
            children: [
              {
                type: 'rect',
                shape: { width: 48, height: 24, r: 12 },
                style: { fill: '#E9E7F2' },
              },
              {
                type: 'text',
                left: 14,
                top: 6,
                style: {
                  text: props.seriesNames[1],
                  fill: '#000',
                  textAlign: 'center',
                  textBaseline: 'middle',
                  fontSize: LABLE_FONT_SIZE,
                },
              },
            ],
          },
          // 准确率
          {
            type: 'group',
            left: 10,
            top: '84%',
            children: [
              {
                type: 'rect',
                shape: { width: 48, height: 24, r: 12 },
                style: { fill: '#E9E7F2' },
              },
              {
                type: 'text',
                left: 9,
                top: 6,
                style: {
                  text: props.seriesNames[2],
                  fill: '#000',
                  textAlign: 'center',
                  textBaseline: 'middle',
                  fontSize: LABLE_FONT_SIZE,
                },
              },
            ],
          },
        ],
        xAxis: {
          type: 'category',
          data: props.dataList.map((i) => i.name),
          // data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月', '总计'],
          axisLine: {
            show: true,
            symbol: ['none', 'arrow'],
            symbolSize: 6,
          },
          axisTick: {
            show: false,
            alignWithLabel: true,
          },
          splitLine: {
            show: true,
            lineStyle: {
              type: 'dashed',
            },
          },
          axisLabel: {
            interval: 0,
          },
        },
        yAxis: {
          type: 'value',
          max: props.showLast
            ? Math.max(...props.dataList.flatMap((i) => [i.value, i.value2]))
            : Math.max(...props.dataList.slice(0, -1).flatMap((i) => [i.value, i.value2])),
          axisLine: {
            show: true,
            symbol: ['none', 'arrow'],
            symbolSize: 6,
          },
          axisTick: {
            show: true,
          },
          splitLine: {
            show: false,
            lineStyle: {
              type: 'dashed',
            },
          },
          nameTextStyle: {
            align: 'left',
            padding: [0, 0, 20, -40],
            fontWeight: 'bold',
          },
          axisLabel: {
            formatter: (value) => {
              return MathUtil[f](value, dot);
            },
            showMaxLabel: true,
            showMinLabel: true,
          },
        },
        series: [
          {
            name: props.seriesNames[0],
            type: 'line',
            data: props.dataList.map((d) => d.value),
            smooth: false,
            connectNulls: true,
            lineStyle: { color: Color.COLOR_BLUE },
            symbol: 'circle',
            symbolSize: 8,
            itemStyle: {
              color: Color.COLOR_BLUE,
            },
            label: {
              show: false,
            },
          },
          {
            name: props.seriesNames[1],
            type: 'line',
            data: props.dataList.map((d) => d.value2),
            smooth: false,
            connectNulls: true,
            lineStyle: { color: Color.COLOR_MAIN_PURPLE },
            symbol: 'circle',
            symbolSize: 8,
            itemStyle: {
              color: '#7D70A6',
            },
            label: {
              show: false,
            },
          },
          {
            type: 'custom',
            renderItem: renderCustomItem,
            z: 100,
            encode: {
              x: 0,
              y: [1, 2],
            },
            data: props.dataList.map((d) => [d.name, d.value, d.value2]),
          },
        ],
      });

      watchEffect(() => {
        if (props.dataList && props.dataList.length) {
          initCharts();
        }
      });

      function initCharts() {
        if (props.option) {
          Object.assign(option, cloneDeep(props.option));
        }
        setOptions(option);
      }
      return { chartRef, zeroPoint };
    },
  });
</script>

<style lang="less" scoped>
  .chart-container {
    padding: 8px;
  }

  @media screen and (max-width: 768px) {
    .chart-container {
      padding: 8px;
    }
  }
</style>
